function observe(data) {
    if (!data || typeof data !== 'object') return;
    new Observer(data);
}

class Observer {
    constructor(value) {
        this.value = value;
        this.walk(value);
    }
    walk(obj) {
        Object.keys(obj).forEach(key => {
            defineReactive(obj, key, obj[key])
        });
    }
}

function defineReactive(obj, key, val) {
    observe(val);
    Object.defineProperty(obj, key, {
        get() {
            // 依赖收集
            Dep.target && dep.addDep(Dep.target);
            return val;
        },
        set(newVal) {
            if (val === newVal) return;
            // 视图更新
            dep.notify();  // 通知watcher触发更新
        }
    })
}



class Vue {
    constructor(options) {
        this.$options = options;
        this.$data = options.data;
        // 处理data变成响应式
        observe(this.$data);
    }
}

class Compile {
    constructor(el, vm) {
        this.$vm = vm;
        this.$el = document.querySelector(el);
        if (this.$el) {
            this.compile(this.$el);
        }
    }
    compile(el) {
        const childNodes = el.childNodes;
        Array.from(childNodes).forEach(node => {
            if (this.isElement(node)) {  // 判断是否是元素节点
                console.log("编译元素" + node.nodeName);
            } else if (this.isInter(node)) { // 判断是否是文本节点
                console.log("编译文本" + node.textContent);
            }
            if (node.childNodes && node.childNodes.length) {
                this.compile(node);
            }
        })
    }
}


class Watcher {
    constructor(vm, key, updater) {
        this.vm = vm;
        this.key = key;
        this.updaterFn = updater;

        Dep.target = this;
        vm[key]  // 触发get
        Dep.target = null;
    }
}

class Dep {
    constructor() {
        this.deps = [];
    }
    addDep(dep) {
        this.deps.push(dep);
    }
    notify() {
        this.deps.forEach(dep => dep.update());
    }
}








const v = new Vue({
    el: "#app",
    template: `<input v-model="msg" /> --- {{msg}}`,
    data: {
        msg: "",  // dep => [msg用在了哪个地方， 又用在了哪个地方]
        msg2: "",
        msg3: "",
    },
})
{/* <p>{{msg}}</p>
<p>{{msg2}}</p>
<p>{{msg3}}</p> */}

// watcher1    key = msg       Dep1 => deps = [watcher1, watcher2]
// watcher2    key = msg2
// watcher3    key = msg3